//===============================================================================
// Microsoft patterns & practices
// Mobile Client Software Factory - July 2006
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Globalization;
using Microsoft.FxCop.Sdk;

namespace Microsoft.Practices.ObjectBuilder.ObGen
{
	public static class MetadataCache
	{
		static Dictionary<Type, TypeNode> types = new Dictionary<Type, TypeNode>();
		static Dictionary<MethodInfo, Method> methods = new Dictionary<MethodInfo, Method>();
		static Dictionary<PropertyInfo, PropertyNode> properties = new Dictionary<PropertyInfo, PropertyNode>();
		static Dictionary<EventInfo, EventNode> events = new Dictionary<EventInfo, EventNode>();

		public static TypeNode GetTypeMetadata(Type type)
		{
			TypeNode node;
			if (types.TryGetValue(type, out node))
				return node;

			node = AssemblyNode.GetAssembly(type.Assembly.ManifestModule.FullyQualifiedName).GetType(Identifier.For(type.Namespace), Identifier.For(type.Name));
			if (node != null)
				types.Add(type, node);
			else
				// For whatever reason, I found this may fail sometimes, and work just fine a minute later.
				throw new ArgumentException(String.Format(
					CultureInfo.CurrentCulture,
					Properties.Resources.CannotLoadMetadata,
					type));

			return node;
		}

		public static Method GetMethodMetadata(MethodInfo info)
		{
			Method node;
			if (methods.TryGetValue(info, out node))
				return node;

			node = Method.GetMethod(info);
			if (node != null)
				methods.Add(info, node);
			else
				// For whatever reason, I found this may fail sometimes, and work just fine a minute later.
				throw new ArgumentException(String.Format(
					CultureInfo.CurrentCulture,
					Properties.Resources.CannotLoadMetadata,
					info));

			return node;
		}

		public static Property GetPropertyMetadata(PropertyInfo info)
		{
			Property property;
			if (properties.TryGetValue(info, out property))
				return property;

			property = Property.GetProperty(info);
			if (property != null)
				properties.Add(info, property);
			else
				// For whatever reason, I found this may fail sometimes, and work just fine a minute later.
				throw new ArgumentException(String.Format(
					CultureInfo.CurrentCulture,
					Properties.Resources.CannotLoadMetadata,
					info));

			return property;
		}

		public static Event GetEventMetadata(EventInfo info)
		{
			Event ev;
			if (events.TryGetValue(info, out ev))
				return ev;

			ev = Event.GetEvent(info);
			if (ev != null)
				events.Add(info, ev);
			else
				// For whatever reason, I found this may fail sometimes, and work just fine a minute later.
				throw new ArgumentException(String.Format(
					CultureInfo.CurrentCulture,
					Properties.Resources.CannotLoadMetadata,
					info));

			return ev;
		}
	}
}
